#include "Daemon.h"
#include "StringUtil.h"
#include "FileUtil.h"
#include <iostream>

namespace BASE{
	void Daemon::setUser(const std::string & user){
		struct passwd * pw = getpwnam(user.c_str());
		if (!pw){
			return;
		}
		setuid(pw->pw_uid);
	}
	
	bool Daemon::runDaemon(const char * pidFileName, const char * stdoutFileName, const char * stderrFileName){
		if (daemon(-1, -1) != 0){
			return false;
		}
		return Daemon::savePidAndDupFd(pidFileName, stdoutFileName, stderrFileName);
	}

	bool Daemon::runForkDaemon(const char * pidFileName, const char * stdoutFileName, const char * stderrFileName){
		pid_t pid;
		pid = fork();
		if (pid < 0){
			return false;
		}
		if (pid > 0){
			exit(0);
		}
		if (setsid() < 0){
			return false;
		}
		//signal(SIGCHLD, SIG_IGN);
		//signal(SIGHUP, SIG_IGN);
		pid = fork();
		if (pid < 0){
			return false;
		}
		if (pid > 0){
			exit(0);
		}
		umask(0);
		return Daemon::savePidAndDupFd(pidFileName, stdoutFileName, stderrFileName);
	}

	bool Daemon::isPidRunning(const std::string & pidFileName){
		std::string content = FileUtil::readAll(pidFileName);
		if (content.empty()){
			return false;
		}
		std::string cmd = "ps -ef |grep -v \"grep\" |awk '{print $2}' | grep ";
		cmd += content;
		FILE * fp = popen(cmd.c_str(), "r");
		if (!fp){
			return false;
		}
		char buf[4096] = {0};
		while(fgets(buf, sizeof(buf) - 1, fp)){
			//std::cout <<strlen(buf) <<  ",buf " << buf<< std::endl;
			if (memcmp(buf, content.c_str(), content.size()) == 0){
				return true;
			}
			memset(buf, 0, sizeof(buf));	
		}
		pclose(fp);
		return false;
	}


	bool Daemon::isProcessRunning(const std::string & processName){
		std::string name = processName;
		size_t pos = processName.find_last_of("/");
		if (pos != std::string::npos){
			name = processName.substr(pos + 1);
		}
		std::ostringstream ss;
		ss << "ps -ef |grep -v \"grep\" | grep " << name;
		FILE * fp = popen(ss.str().c_str(), "r");
		if(!fp){
			return false;
		}
		char buf[4096] = {0};
		while(fgets(buf, sizeof(buf), fp)){
			//std::cout << strlen(buf)  << ",buf " << buf << std::endl;
			if(strlen(buf) > 0){
				return true;
			}
		}
		pclose(fp);
		return false;
	}

	bool Daemon::savePidAndDupFd(const char * pidFileName, const char * stdoutFileName, const char * stderrFileName){
		if (pidFileName != NULL){
			FILE * pidFile = fopen(pidFileName,"w+");
			if (!pidFile){
				return false;
			}
			std::string pid = toString(getpid());
			fwrite(pid.c_str(), pid.size(), 1, pidFile);
			fclose(pidFile);
		}
		if (stdoutFileName){
			//std::cout << stdoutFileName << std::endl;
			int fd = open(stdoutFileName, O_APPEND | O_CREAT | O_RDWR, 0644);
			dup2(fd, STDOUT_FILENO);
			close(fd);
		}
		if (stderrFileName){
			int fd = open(stderrFileName, O_APPEND|O_CREAT | O_RDWR, 0644);
			dup2(fd, STDERR_FILENO);
			close(fd);
		}
		return true;
	}

}
